package com.ww.exercise.coroutine.easy.q3

import kotlinx.coroutines.*
import java.util.*

// 数据类
data class Order(val id: String, val amount: Double, val userId: String)

// 计算结果数据类
data class CalculationResult(val totalOrders: Int, val averageAmount: Double)

/**
 * 不指定调度器可能带来的问题
 * ==========================================================================
 * 1、主线程阻塞风险
 * 如果主线程中直接执行这些操作而不指定调度器，可能会阻塞主线程，导致应用无响应
 * 2、资源利用不合理
 *   2.1、IO密集型任务默认可能使用Dispatchers.Main或Dispatchers.Default，导致线程在等待IO时闲置，没有充分利用资源
 *   2.2、计算密集型任务如果使用Dispatchers.IO，会占用本应用于IO操作的线程，影响整体性能
 * 3、线程池配置不匹配
 *   3.1、Dispatchers.IO针对IO操作优化，线程池更大，适合大量等待操作
 *   3.2、Dispatchers.Default的线程数与CPU核心数相关，适合CPU密集型任务
 *   3.3、错误的调度器会导致线程资源浪费或竞争
 * 4、潜在的性能问题
 *   4.1、计算密集型任务如果在IO线程池执行，可能会导致IO操作等待计算完成，延长整体响应时间
 *   4.2、大量IO操作如果在默认调度器执行，可能会耗尽线程池，导致任务排队等待
 * ==========================================================================
 * 通过显式指定调度器，可以确保不同类型的任务在最适合它们的线程池上运行，从而提高应用的整体性能和响应性
 */
fun main() = runBlocking {
    println("主线程启动：${Thread.currentThread().name}")
    val result = processComplexTask()
    println("最终计算结果：总订单数=${result.totalOrders}，平均订单金额=${result.averageAmount}")
    println("主线程结束：${Thread.currentThread().name}")
}

suspend fun processComplexTask(): CalculationResult = coroutineScope {
    // 1.IO密集型操作：查询数据库，指定Dispatchers.IO
    // 数据库查询是 IO 密集型操作，用 async(Dispatchers.IO) 可以在独立协程中并行执行（如果有多个查询，可同时启动多个 async）。
    val ordersDeferred = async(Dispatchers.IO) {
        fetchOrdersFromDatabase()
    }

    // 等待IO操作完成
    val orders = ordersDeferred.await()

    // 统计计算是 CPU 密集型操作，依赖数据库查询的结果，无需并行，因此用 withContext(Dispatchers.Default) 切换到适合计算的线程池即可，更轻量且清晰。
    val result = withContext(Dispatchers.Default) {
        calculateOrderStatistics(orders)
    }

    result
}

// 模拟IO密集型操作：查询数据库
private suspend fun fetchOrdersFromDatabase(): List<Order> {
    println("数据库查询开始 - 线程：${Thread.currentThread().name}")

    // 模拟数据库查询延迟
    kotlinx.coroutines.delay(1000)

    // 生成模拟数据
    val random = Random()
    val orders = mutableListOf<Order>()
    for (i in 1..1000) {
        orders.add(
            Order(
                id = "ORDER-${i}",
                amount = 100 + random.nextDouble() * 900,
                userId = "USER-${random.nextInt(100)}"
            )
        )
    }

    println("数据库查询完成 - 线程${Thread.currentThread().name}")
    return orders
}

// 模拟计算密集型操作：复杂聚合计算
private fun calculateOrderStatistics(orders: List<Order>): CalculationResult {
    println("计算开始 - 线程：${Thread.currentThread().name}")

    // 模拟复杂计算
    var totalAmount = 0.0
    val userOrderCount = mutableMapOf<String, Int>()

    // 复杂计算逻辑
    for (order in orders) {
        totalAmount += order.amount
        userOrderCount[order.userId] = (userOrderCount[order.userId] ?: 0) + 1

        // 模拟计算复杂度
        for (i in 1..1000) {
            Math.sqrt(order.amount * i)
        }
    }

    val averageAmount = totalAmount / orders.size
    val totalOrders = orders.size
    return CalculationResult(totalOrders, averageAmount)
}